home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / sbin / update-initramfs < prev    next >
Text File  |  2009-07-07  |  11KB  |  554 lines

  1. #!/bin/sh
  2.  
  3. STATEDIR=/var/lib/initramfs-tools
  4. BOOTDIR=/boot
  5. CONF=/etc/initramfs-tools/update-initramfs.conf
  6. KPKGCONF=/etc/kernel-img.conf
  7. USETRIGGERS=true
  8. mode=""
  9. version=""
  10.  
  11. set -e
  12.  
  13. [ -r ${CONF} ] && . ${CONF}
  14.  
  15. if       $USETRIGGERS                        \
  16.     && [ x"$DPKG_MAINTSCRIPT_PACKAGE" != x ]        \
  17.     && [ $# = 1 ]                         \
  18.     && [ x"$1" = x-u ]                    \
  19.     && dpkg-trigger --check-supported 2>/dev/null
  20. then
  21.     if dpkg-trigger --no-await update-initramfs; then
  22.         echo "update-initramfs: deferring update (trigger activated)"
  23.         exit 0
  24.     fi
  25. fi
  26.  
  27. usage()
  28. {
  29.     if [ -n "${1}" ]; then
  30.         printf "${@}\n\n" >&2
  31.     fi
  32.     cat >&2 << EOF
  33. Usage: ${0} [OPTION]...
  34.  
  35. Options:
  36.  -k [version]    Specify kernel version or 'all'
  37.  -c        Create a new initramfs
  38.  -u        Update an existing initramfs
  39.  -d        Remove an existing initramfs
  40.  -t        Take over a custom initramfs with this one
  41.  -b        Set alternate boot directory
  42.  -v        Be verbose
  43.  -h        This message
  44.  
  45. EOF
  46.     exit 1
  47. }
  48.  
  49. # chroot check
  50. chrooted()
  51. {
  52.         # borrowed from udev's postinst
  53.         if [ "$(stat -c %d/%i /)" = "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ]; then
  54.                 # the devicenumber/inode pair of / is the same as that of
  55.                 # /sbin/init's root, so we're *not* in a chroot and hence
  56.                 # return false.
  57.                 return 1
  58.         fi
  59.         return 0
  60. }
  61.  
  62. mild_panic()
  63. {
  64.     if [ -n "${1}" ]; then
  65.         printf "${@}\n" >&2
  66.     fi
  67.     exit 0
  68. }
  69.  
  70. panic()
  71. {
  72.     if [ -n "${1}" ]; then
  73.         printf "${@}\n" >&2
  74.     fi
  75.     exit 1
  76. }
  77.  
  78. verbose()
  79. {
  80.     if [ "${verbose}" = 1 ]; then
  81.         printf "${@}\n"
  82.     fi
  83. }
  84.  
  85. version_exists()
  86. {
  87.     [ -e "${STATEDIR}/${1}" ] && [ -e "${initramfs}" ]
  88.     return $?
  89. }
  90.  
  91. set_initramfs()
  92. {
  93.     initramfs="${BOOTDIR}/initrd.img-${version}"
  94. }
  95.  
  96.  
  97. # backup initramfs while running
  98. backup_initramfs()
  99. {
  100.     [ ! -r "${initramfs}" ] && return 0
  101.     initramfs_bak="${initramfs}.dpkg-bak"
  102.     [ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}"
  103.     ln -f "${initramfs}" "${initramfs_bak}" \
  104.         || cp -a "${initramfs}" "${initramfs_bak}"
  105.     verbose "Keeping ${initramfs_bak}"
  106. }
  107.  
  108. # keep booted initramfs
  109. backup_booted_initramfs()
  110. {
  111.     initramfs_bak="${initramfs}.dpkg-bak"
  112.  
  113.     # first time run thus no backup
  114.     [ ! -r "${initramfs_bak}" ] && return 0
  115.  
  116.     # chroot with no /proc
  117.     [ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0
  118.  
  119.     # no kept backup wanted
  120.     [ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0
  121.  
  122.     # no backup yet
  123.     if [ ! -r "${initramfs}.bak" ]; then
  124.         mv -f ${initramfs_bak} "${initramfs}.bak"
  125.         verbose "Backup ${initramfs}.bak"
  126.         return 0
  127.     fi
  128.  
  129.     # keep booted initramfs
  130.     uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime)
  131.     if [ -n "$uptime_days" ]; then
  132.         boot_initramfs=$(find "${initramfs}.bak" -mtime +${uptime_days})
  133.     fi
  134.     if [ -n "${boot_initramfs}" ]; then
  135.         mv -f "${initramfs_bak}" "${initramfs}.bak"
  136.         verbose "Backup ${initramfs}.bak"
  137.         return 0
  138.     fi
  139.     verbose "Removing current backup ${initramfs_bak}"
  140.     rm -f ${initramfs_bak}
  141. }
  142.  
  143. # nuke generated copy
  144. remove_initramfs()
  145. {
  146.     [ -z "${initramfs_bak}" ] && return 0
  147.     rm -f "${initramfs_bak}"
  148.     verbose "Removing ${initramfs_bak}"
  149. }
  150.  
  151.  
  152. generate_initramfs()
  153. {
  154.     echo "update-initramfs: Generating ${initramfs}"
  155.     OPTS="-o"
  156.     if [ "${verbose}" = 1 ]; then
  157.         OPTS="-v ${OPTS}"
  158.     fi
  159.     if mkinitramfs ${OPTS} "${initramfs}.new" "${version}"; then
  160.         mv -f "${initramfs}.new" "${initramfs}"
  161.         set_sha1
  162.     else
  163.         mkinitramfs_return="$?"
  164.         remove_initramfs
  165.         rm -f "${initramfs}.new"
  166.         if [ "$mkinitramfs_return" = "2" ]; then
  167.             # minversion wasn't met, exit 0
  168.             exit 0
  169.         fi
  170.         echo "update-initramfs: failed for ${initramfs}"
  171.         exit $mkinitramfs_return
  172.     fi
  173. }
  174.  
  175. # lilo call
  176. run_lilo()
  177. {
  178.     # show lilo errors on failure
  179.     if ! lilo -t  > /dev/null 2>&1 ; then
  180.         echo "ERROR lilo fails for new ${initramfs}:"
  181.         echo
  182.         lilo -t
  183.     fi
  184.     lilo
  185. }
  186.  
  187. # check if lilo is on mbr
  188. mbr_check()
  189. {
  190.     # try to discover grub and be happy
  191.     # FIXME: check grub2 /boot/grub/grub.cfg
  192.     [ -r /boot/grub/menu.lst ] \
  193.         && groot=$(awk '/^root/{print substr($2, 2, 3); exit}' \
  194.             /boot/grub/menu.lst)
  195.     [ -e /boot/grub/device.map ] && [ -n "${groot}" ] \
  196.         && dev=$(awk "/${groot}/{ print \$NF}" /boot/grub/device.map)
  197.     [ -n "${dev}" ] && [ -r ${dev} ] \
  198.         && dd if="${dev}" bs=512 skip=0 count=1 2> /dev/null \
  199.         | grep -q GRUB && return 0
  200.  
  201.     # check out lilo.conf for validity
  202.     boot=$(awk -F = '/^boot=/{ print $2}' /etc/lilo.conf)
  203.     [ -z "${boot}" ] && return 0
  204.     case ${boot} in
  205.     /dev/md/*)
  206.         if [ -r /proc/mdstat ]; then
  207.             MD=${boot#/dev/md/}
  208.             boot="/dev/$(awk "/^md${MD}/{print substr(\$5, 1, 3)}" \
  209.             /proc/mdstat)"
  210.         fi
  211.         ;;
  212.     /dev/md*)
  213.         if [ -r /proc/mdstat ]; then
  214.             MD=${boot#/dev/}
  215.             boot="/dev/$(awk "/^${MD}/{print substr(\$5, 1, 3)}" \
  216.             /proc/mdstat)"
  217.         fi
  218.         ;;
  219.     esac
  220.     [ ! -r "${boot}" ] && return 0
  221.     dd if="${boot}" bs=512 skip=0 count=1 2> /dev/null | grep -q LILO \
  222.         && run_lilo && return 0
  223.  
  224.     # no idea which bootloader is used
  225.     echo
  226.     echo "WARNING: grub and lilo installed."
  227.     echo "If you use grub as bootloader everything is fine."
  228.     echo "If you use lilo as bootloader you must run lilo!"
  229.     echo
  230. }
  231.  
  232. # Invoke bootloader
  233. run_bootloader()
  234. {
  235.     # if both lilo and grub around, figure out if lilo needs to be run
  236.     if [ -x "$(command -v update-grub)" ] || [ -e /boot/grub/menu.lst ] \
  237.     || [ -e /boot/grub/grub.cfg ]; then
  238.         if [ -e /etc/lilo.conf ] && [ -x /sbin/lilo ]; then
  239.             [ -r "${KPKGCONF}" ] && \
  240.             do_b=$(awk  '/^do_bootloader/{print $3}' "${KPKGCONF}")
  241.             if [ "${do_b}" = "yes" ] || [ "${do_b}" = "Yes" ] \
  242.                 || [ "${do_b}" = "YES" ]; then
  243.                 run_lilo
  244.                 return 0
  245.             elif [ "${do_b}" = "no" ] || [ "${do_b}" = "No" ] \
  246.                 || [ "${do_b}" = "NO" ]; then
  247.                 return 0
  248.             else
  249.                 mbr_check
  250.                 return 0
  251.             fi
  252.         fi
  253.         return 0
  254.     fi
  255.     if [ -r /etc/lilo.conf ] && [ -x /sbin/lilo ]; then
  256.         run_lilo
  257.         return 0
  258.     fi
  259.     if [ -x /sbin/elilo ]; then
  260.         elilo
  261.         return 0
  262.     fi
  263.     if [ -r /etc/zipl.conf ]; then
  264.         zipl
  265.     fi
  266.     if [ -r /etc/kernel-img.conf ] && grep -q '^postinst_hook[[:space:]]*=[[:space:]]*[^[:space:]]' /etc/kernel-img.conf; then
  267.         if flash-kernel --supported >/dev/null 2>&1; then
  268.             flash-kernel
  269.         fi
  270.     fi
  271. }
  272.  
  273. compare_sha1()
  274. {
  275.     sha1sum "${initramfs}" | diff "${STATEDIR}/${version}" - >/dev/null 2>&1
  276.     return $?
  277. }
  278.  
  279. # Note that this must overwrite so that updates work.
  280. set_sha1()
  281. {
  282.     sha1sum "${initramfs}" > "${STATEDIR}/${version}"
  283. }
  284.  
  285. delete_sha1()
  286. {
  287.     rm -f "${STATEDIR}/${version}"
  288. }
  289.  
  290. # ro /boot is not modified
  291. ro_boot_check()
  292. {
  293.     # check irrelevant inside of a chroot
  294.     if [ ! -r /proc/mounts ] || chrooted; then
  295.         return 0
  296.     fi
  297.  
  298.     boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \
  299.         && $2 == "/boot") print "ro"}' /proc/mounts)
  300.     if [ -n "${boot_opts}" ]; then
  301.         echo "WARNING: /boot is ro mounted."
  302.         echo "update-initramfs: Not updating ${initramfs}"
  303.         exit 0
  304.     fi
  305. }
  306.  
  307. get_sorted_versions()
  308. {
  309.     version_list=""
  310.  
  311.     for gsv_x in "${STATEDIR}"/*; do
  312.         gsv_x="$(basename "${gsv_x}")"
  313.         if [ "${gsv_x}" = '*' ]; then
  314.             return 0
  315.         fi
  316.         worklist=""
  317.         for gsv_i in $version_list; do
  318.             if dpkg --compare-versions "${gsv_x}" '>' "${gsv_i}"; then
  319.                 worklist="${worklist} ${gsv_x} ${gsv_i}"
  320.                 gsv_x=""
  321.             else
  322.                 worklist="${worklist} ${gsv_i}"
  323.             fi
  324.         done
  325.         if [ "${gsv_x}" != "" ]; then
  326.             worklist="${worklist} ${gsv_x}"
  327.         fi
  328.         version_list="${worklist}"
  329.     done
  330.  
  331.     verbose "Available versions: ${version_list}"
  332. }
  333.  
  334. set_current_version()
  335. {
  336.     if [ -f /boot/initrd.img-`uname -r` ]; then
  337.         version=`uname -r`
  338.     fi
  339. }
  340.  
  341. set_linked_version()
  342. {
  343.     if [ -L /initrd.img -a -e /initrd.img ]; then
  344.         linktarget="$(basename "$(readlink /initrd.img)")"
  345.     fi
  346.  
  347.     if [ -L /boot/initrd.img -a -e /boot/initrd.img ]; then
  348.         linktarget="$(basename "$(readlink /boot/initrd.img)")"
  349.     fi
  350.  
  351.     if [ -z "${linktarget}" ]; then
  352.         return
  353.     fi
  354.  
  355.     version="${linktarget##initrd.img-}"
  356. }
  357.  
  358. set_highest_version()
  359. {
  360.     get_sorted_versions
  361.     set -- ${version_list}
  362.     version=${1}
  363. }
  364.  
  365. create()
  366. {
  367.     if [ -z "${version}" ]; then
  368.         usage "Create mode requires a version argument"
  369.     fi
  370.  
  371.     set_initramfs
  372.  
  373.     if [ "${takeover}" = 0 ]; then
  374.         if version_exists "${version}"; then
  375.             panic "Cannot create version ${version}: already exists"
  376.         fi
  377.  
  378.         if [ -e "${initramfs}" ]; then
  379.             panic "${initramfs} already exists, cannot create."
  380.         fi
  381.     fi
  382.  
  383.     generate_initramfs
  384. }
  385.  
  386. update()
  387. {
  388.     if [ "${update_initramfs}" = "no" ]; then
  389.         echo "update-initramfs: Not updating initramfs."
  390.         exit 0
  391.     fi
  392.  
  393.     if [ -z "${version}" ]; then
  394.         set_linked_version
  395.     fi
  396.  
  397.     if [ -z "${version}" ]; then
  398.         set_highest_version
  399.     fi
  400.  
  401.     if [ -z "${version}" ]; then
  402.         set_current_version
  403.     fi
  404.  
  405.     if [ -z "${version}" ]; then
  406.         verbose "Nothing to do, exiting."
  407.         exit 0
  408.     fi
  409.  
  410.     set_initramfs
  411.  
  412.     ro_boot_check
  413.  
  414.     altered_check
  415.  
  416.     backup_initramfs
  417.  
  418.     generate_initramfs
  419.  
  420.     run_bootloader
  421.  
  422.     backup_booted_initramfs
  423. }
  424.  
  425. delete()
  426. {
  427.     if [ -z "${version}" ]; then
  428.         usage "Delete mode requires a version argument"
  429.     fi
  430.  
  431.     set_initramfs
  432.  
  433.     if [ ! -e "${initramfs}" ]; then
  434.         panic "Cannot delete ${initramfs}, doesn't exist."
  435.     fi
  436.  
  437.     if ! version_exists "${version}"; then
  438.         panic "Cannot delete version ${version}: Not created by this utility."
  439.     fi
  440.  
  441.     altered_check
  442.  
  443.     echo "update-initramfs: Deleting ${initramfs}"
  444.  
  445.     delete_sha1
  446.  
  447.     rm -f "${initramfs}"
  448. }
  449.  
  450. # Check for update mode on existing and modified initramfs
  451. altered_check()
  452. {
  453.     # No check on takeover
  454.     [ "${takeover}" = 1 ] && return 0
  455.     if [ ! -e "${initramfs}" ]; then
  456.         mild_panic "${initramfs} does not exist. Cannot update."
  457.     fi
  458.     if ! compare_sha1; then
  459.         echo "update-initramfs: ${initramfs} has been altered." >&2
  460.         mild_panic "update-initramfs: Cannot update. Override with -t option."
  461.     fi
  462. }
  463.  
  464. # Defaults
  465. verbose=0
  466. yes=0
  467. # We default to takeover=1 in Ubuntu, but not Debian
  468. takeover=1
  469.  
  470. ##
  471.  
  472. while getopts "k:cudyvtb:h?" flag; do
  473.     case "${flag}" in
  474.     k)
  475.         version="${OPTARG}"
  476.         ;;
  477.     c)
  478.         mode="c"
  479.         ;;
  480.     d)
  481.         mode="d"
  482.         ;;
  483.     u)
  484.         mode="u"
  485.         ;;
  486.     v)
  487.         verbose="1"
  488.         ;;
  489.     y)
  490.         yes="1"
  491.         ;;
  492.     t)
  493.         takeover="1"
  494.         ;;
  495.     b)
  496.         BOOTDIR="${OPTARG}"
  497.         if [ ! -d "${BOOTDIR}" ]; then
  498.             echo "Error: ${BOOTDIR} is not a directory."
  499.             exit 1
  500.         fi
  501.         ;;
  502.     h|?)
  503.         usage
  504.         ;;
  505.     esac
  506. done
  507.  
  508. # Validate arguments
  509. if [ -z "${mode}" ]; then
  510.     usage "You must specify at least one of -c, -u, or -d."
  511. fi
  512.  
  513. if [ "${version}" = "all" ] \
  514.     || ( [ "${update_initramfs}" = "all" ] && [ -z "${version}" ] ); then
  515.     : FIXME check for --yes, and if not ask are you sure
  516.     get_sorted_versions
  517.     if [ -z "${version_list}" ]; then
  518.         verbose "Nothing to do, exiting."
  519.         exit 0
  520.     fi
  521.  
  522.     OPTS="-b ${BOOTDIR}"
  523.     if [ "${verbose}" = "1" ]; then
  524.         OPTS="${OPTS} -v"
  525.     fi
  526.     if [ "${takeover}" = "1" ]; then
  527.         OPTS="${OPTS} -t"
  528.     fi
  529.     if [ "${yes}" = "1" ]; then
  530.         OPTS="${OPTS} -y"
  531.     fi
  532.     for u_version in ${version_list}; do
  533.         # Don't stop if one version doesn't work.
  534.         set +e
  535.         verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"
  536.         "${0}" -${mode} -k "${u_version}" ${OPTS}
  537.         set -e
  538.     done
  539.     exit 0
  540. fi
  541.  
  542.  
  543. case "${mode}" in
  544.     c)
  545.         create
  546.         ;;
  547.     d)
  548.         delete
  549.         ;;
  550.     u)
  551.         update
  552.         ;;
  553. esac
  554.